<?php

/**
 * This file is part of the Pagizer package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright   Copyright (c) 2010 Advisa (http://www.advisa.fr)
 * @author      Pagizer Core Team <team@pagizer.org>
 * @package     Pagizer
 * @subpackage  backoffice
 */

class m_backoffice_services_SelectService extends f_core_Service
{
    private $rootNode;
    private $modelsToGet;
    private $currentId;
    private $showRoot;
    private $isRecursive;
    private $folderModule;
    private $checkRights;
    private $removedIds = array();
    private $disabledIds = array();
    private $disabledModels = array();
    private $count = 0;

    private $selectNodes = array();
	
	/**
	 * @return m_backoffice_services_SelectService
	 */
	private function __construct()
	{
        $this->rootNode = f_core_Context::getInstance()->getContext('currentWebsite');
        $this->modelsToGet = array('modules_website/website', 'modules_website/menu');
        $this->showRoot = true;
        $this->isRecursive = true;
        $this->folderModule = 'website';
        $this->checkRights = true;

		return $this;
	}
	
	/**
	 * Get instance
	 *
	 * @return m_backoffice_services_SelectService
	 */
	public static function getInstance()
	{
        return new self();
	}

    /**
     * Define the tree root node by his id
     *
     * @param integer $docId
     * @param string $docLang
     * @return m_backoffice_services_SelectService
     */
    public function setRootNodeById($docId, $docLang = null)
    {
        $docProvider = $this->getDocumentProvider();
        $this->rootNode = null;

        if($docProvider->checkDocument($docId, $docLang))
        {
            $this->rootNode = $docProvider->getByUniqueId($docId, $docLang);
        }
        
        return $this;
    }

    /**
     * Define the tree root node by a module name
     *
     * @param string $moduleName
     * @return m_backoffice_services_SelectService
     */
    public function setRootNodeByModuleName($moduleName)
    {
        $this->rootNode = m_backoffice_services_RootNodeService::getInstance()->getModuleRootNode($moduleName);
        return $this;
    }

    /**
     * Define the documents to get in the tree by models
     *
     * @param array $models
     * @return m_backoffice_services_SelectService
     */
    public function setModelsToGet($models)
    {
        $this->modelsToGet = array();
        
        if(!is_array($models) && is_string($models))
        {
            $models = array($models);
        }

        foreach($models as $model)
        {
            $model = str_replace('modules_', '', $model);
            $this->modelsToGet[] = 'modules_'.$model;
        }

        return $this;
    }

    /**
     * Define current selected id
     *
     * @param integer $docId
     * @return m_backoffice_services_SelectService
     */
    public function currentId($docId)
    {
        $this->currentId = $docId;
        return $this;
    }

    /**
     *
     * @param <type> $value
     * @return m_backoffice_services_SelectService
     */
    public function showRoot($value)
    {
        $this->showRoot = (bool) $value;
        return $this;
    }

    /**
     *
     * @param <type> $value
     * @return m_backoffice_services_SelectService
     */
    public function setRecursive($value)
    {
        $this->isRecursive = (bool) $value;
        return $this;
    }

    /**
     *
     * @param <type> $value
     * @return m_backoffice_services_SelectService
     */
    public function setFolderModule($value)
    {
        $this->folderModule = $value;
        return $this;
    }

    /**
     *
     * @param <type> $value
     * @return m_backoffice_services_SelectService
     */
    public function checkRights($value)
    {
        $this->checkRights = (bool) $value;
        return $this;
    }

    /**
     *
     * @param <type> $value
     * @return m_backoffice_services_SelectService
     */
    public function unsetId($value)
    {
        if(is_array($value))
        {
            foreach($value as $id)
            {
                $this->removedIds[] = $id;
            }
        }
        else
        {
            $this->removedIds[] = $value;
        }
        return $this;
    }

    /**
     *
     * @param <type> $value
     * @return m_backoffice_services_SelectService
     */
    public function disableId($value)
    {
        if(is_array($value))
        {
            foreach($value as $id)
            {
                $this->disabledIds[] = $id;
            }
        }
        else
        {
            $this->disabledIds[] = $value;
        }
        return $this;
    }

    /**
     *
     * @param <type> $value
     * @return m_backoffice_services_SelectService
     */
    public function disableModel($value)
    {
        if(is_array($value))
        {
            foreach($value as $id)
            {
                $this->disabledModels[] = $id;
            }
        }
        else
        {
            $this->disabledModels[] = $value;
        }
        return $this;
    }

    private function isDisabled($doc)
    {
        if(in_array($doc->getUniqueId(), $this->disabledIds))
        {
            return true;
        }

        if(in_array($doc->getModel(), $this->disabledModels))
        {
            return true;
        }
        return false;
    }

    /**
     * Function to make hierarchical select <select><option value=tab[0] selected=tab2>tab1</option>
     * @return m_backoffice_services_SelectService
     */
	public function execute()
	{
        $rootNode = $this->rootNode;

		$subGroup = $this->getChildDocuments($rootNode->getUniqueId());

        if($this->showRoot)
        {
            $root['value'] = $rootNode->getUniqueId();
            $root['label'] = $rootNode->getModel() == 'modules_backoffice/rootNode' ? '/' : $rootNode->getLabel();
            $root['isSelected'] = $rootNode->getUniqueId() == $this->currentId;
            $root['authorization'] = true;
            $root['disabled'] = $this->isDisabled($rootNode);
            $res = array($root);
            $res[] = $subGroup;
            $subGroup = $res;
        }

		$this->readChildDocuments($subGroup, 0);

		return $this;
	}

    public function getSelectContent()
    {
        return $this->selectNodes;
    }

    public function getSelectableItemsNb()
    {
        return $this->count;
    }

	/*
	 * Get the child document from and Id.
	 * @return array
	 */
    private $valid = true;
	private function getChildDocuments($docId)
	{
		$documentProvider = f_document_Provider::getInstance();
        $document = $this->getDocumentProvider()->getByUniqueId($docId);
		$groupsData = f_relation_ManagerNew::getInstance($document)->getChilds()->withModel($this->modelsToGet)->retrieveDocuments();
        $subGroupData = array();

		foreach ($groupsData as $data)
		{
            if(in_array($data->getUniqueId(), $this->removedIds))
            {
                continue;
            }

            if(!is_null($this->folderModule) && $data->getModel() == 'modules_backoffice/folder')
            {
                if($data->getModule() != $this->folderModule)
                {
                    continue;
                }
            }
            
            $authorization = true;
            if($this->checkRights)
            {
                $user = $this->getUser();

                if(is_object($user) && $user->getModel() == 'modules_users/user')
                {
                    $authorization = $user->hasDocRight($data, $data->getDocumentModuleName(), $this->checkRights) ? true : false;
                }
            }

            $isSelected = false;
            if($authorization == true)
            {
                if(!is_null($this->currentId) && $data->getUniqueId() == $this->currentId)
                {
                    $isSelected = true;
                }
                else
                {
                    if($this->valid == true && $this->showRoot == false)
                    {
                        $this->valid = false;
                        $isSelected = true;
                    }
                }
            }

            $subGroupData[] = array('value' => $data->getUniqueId(), 'label' => $data->getLabel(), 'isSelected' => $isSelected, 'authorization' => $authorization, 'disabled' => $this->isDisabled($data));

            if($this->isRecursive)
            {
                $subGroup = $this->getChildDocuments($data->getUniqueId());
                
                if(!empty($subGroup))
                {
                    $subGroupData[] = $subGroup;
                }
            }
		}

		return $subGroupData;
	}

	private function readChildDocuments($subGroup, $level = 0, $folderModule = null)
	{
        $i=1;
		foreach($subGroup as $data)
		{
			if(isset($data[0]) && is_array($data[0]) && !empty($data[0]))
			{
				$level2 = $level + 0.9;
				$this->readChildDocuments($data, $level2);
			}
			else
			{
                $arbo = '';
				if($level > 0)
				{
					$arbo = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $level);
					$nb = count($subGroup);

					$arbo .= $nb == $i ? "└ " : "├ ";
				}

				$this->selectNodes[] = array(   'value' => $data['value'],
                                                'label' => $arbo . $data['label'],
                                                'selected' => $data['isSelected'],
                                                'authorization' => $data['authorization'],
                                                'disabled' => $data['disabled']);

                if($data['disabled'] == false)
                {
                    $this->count++;
                }
			}

			$i++;
		}
	}
}